#ifndef _CONSOLE_H_
#define _CONSOLE_H_

/*
Copyright (C) 2011 Salil Bhagurkar

This file is part of illusion

illusion is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

illusion is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with illusion.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <kernel/types.h>
#include <kernel/config.h>

//Console flags
#define CONSOLE_BUFFERED (1 << 0) //Buffer managed API if set, 'write' if not


struct console_driver {
	u32 flags;
	char *buffer; //A buffer to which the console management will write to update displayed data
	//This is allocated by the console management system
	int (*update_buffer)(uint_t x, uint_t y, uint_t width, uint_t height); //Function that must be implemented
	//by the driver to update data from the buffer to the display
	int (*update_hardware_cursor)(); //Function in driver to update hardware cursor location
	int (*update_size)(); //Function in driver, called to update the changed size in this structure
	int (*init)(); //Function in driver, called to initialize the display and get the parameters
	//This function is used by drivers who do not require buffers
	int (*write)(char *stream, uint_t length);
	uint_t cursor_x, cursor_y; //Cursor location
	uint_t width, height; //Size: set by the console driver
	//Whether output should be directed to this console driver
	bool active;
	struct console_driver *next, *prev;
};


void console_writechar(char c);
void console_write(char *stream, uint_t len);
void console_printf(char *fmt, ...);
void console_hex(void *start, uint_t len);
void console_hex2(void *start, uint_t len);
void console_debug(const char *file, const char *function, uint_t lineno, char *fmt, ...);
void console_initmsg(const char *file, const char *function, uint_t lineno, char *fmt, ...);
void console_fatal_error(const char *file, const char *function, uint_t lineno, char *fmt, ...);


#ifdef CONFIG_DEBUG
#define debug(f, a...)						\
	console_debug(__FILE__, __func__, __LINE__, f, ##a)
#else
#define debug
#endif

#ifdef CONFIG_INITMSG
#define initmsg(f, a...)					\
	console_initmsg(__FILE__, __func__, __LINE__, f, ##a)
#else
#define initmsg
#endif


#if defined(CONFIG_ASSERT_FATAL)

#define assertv(condition, f, a...)			\
{\
	if(!(condition)) console_fatal_error(__FILE__, __func__, __LINE__, f, ##a); \
}

#define assert(condition)					\
{\
	if(!(condition)) console_fatal_error(__FILE__, __func__, __LINE__, "Check!\n"); \
}

#elif defined(CONFIG_ASSERT_LOG)

#define assertv(condition, f, a...)			\
{\
	if(!(condition)) console_printf(__FILE__, __func__, __LINE__, f, ##a); \
}

#define assert(condition)					\
{\
	if(!(condition)) console_printf(__FILE__, __func__, __LINE__, "Check!\n"); \
}

#else

#define assertv
#define assert

#endif

void debug_break_function();

void register_console_driver(struct console_driver *driver);
void unregister_console_driver(struct console_driver *driver);
int console_sys_init();
int console_init();
int console_vfs_init();

#endif /* MEMORY_H_ */
